package com.kning.mastermind;

import java.util.HashSet;
import java.util.Objects;

/**
 * MastermindUtils
 * E4b - 针对四位元素的专用方法
 *
 * @author ning
 **/
public class MastermindUtils {

    public static final HashSet<Integer> setForCheck = new HashSet<>(1 << 2);

    public static final int A4B0 = 0b01000000;

    /**
     * e4b合法校验 -- 每位数字都不相同
     *
     * @param element4b element4b
     * @return boolean
     */
    public static boolean MastermindCheckForE4b(Element4b element4b) {
        if (Objects.isNull(element4b)) {
            return false;
        }
        setForCheck.clear();
        setForCheck.add(element4b.getB1());
        setForCheck.add(element4b.getB2());
        setForCheck.add(element4b.getB3());
        setForCheck.add(element4b.getB4());
        return setForCheck.size() == 4;
    }

    /**
     * e4b获取匹配结果
     *
     * @param guess  guess - 本次猜测
     * @param result result - 目标结果
     * @return int A值 - 高四位, B值 - 低四位, A0B0 - 00 00, A1B1 - 01 01, A2B1 - 10 01
     */
    public static int MastermindMatchForE4b(Element4b guess, Element4b result) {
        // 计算A值 - 高四位, B值 - 低四位
        int A = 0, B = 0;
        A += guess.getB1() == result.getB1() ? 1 : 0;
        A += guess.getB2() == result.getB2() ? 1 : 0;
        A += guess.getB3() == result.getB3() ? 1 : 0;
        A += guess.getB4() == result.getB4() ? 1 : 0;

        setForCheck.clear();
        setForCheck.addAll(guess.getBitSet());
        setForCheck.retainAll(result.getBitSet());
        B = setForCheck.size() - A;

        return (A << 4) + B;
    }

    /**
     * e4b获取匹配结果 - 线程安全版本
     *
     * @param guess  guess - 本次猜测
     * @param result result - 目标结果
     * @return int A值 - 高四位, B值 - 低四位, A0B0 - 00 00, A1B1 - 01 01, A2B1 - 10 01
     */
    public static int concurrentMatchForE4b(Element4b guess, Element4b result) {
        HashSet<Integer> localSetForCheck = new HashSet<>(1 << 2);
        // 计算A值 - 高四位, B值 - 低四位
        int A = 0, B = 0;
        A += guess.getB1() == result.getB1() ? 1 : 0;
        A += guess.getB2() == result.getB2() ? 1 : 0;
        A += guess.getB3() == result.getB3() ? 1 : 0;
        A += guess.getB4() == result.getB4() ? 1 : 0;

        localSetForCheck.clear();
        localSetForCheck.addAll(guess.getBitSet());
        localSetForCheck.retainAll(result.getBitSet());
        B = localSetForCheck.size() - A;

        return (A << 4) + B;
    }

    /**
     * 缩减结果集
     *
     * @param resultSet   resultSet
     * @param guess       guess
     * @param matchResult matchResult
     * @return HashSet<Element4b>
     */
    public static HashSet<Element4b> getNewResultSetE4b(HashSet<Element4b> resultSet, Element4b guess, int matchResult) {
        HashSet<Element4b> newResultSet = new HashSet<>();
        if (matchResult == MatchResultEnum.A4B0.value) {
            newResultSet.add(guess);
            return newResultSet;
        }
        for (Element4b element4b : resultSet) {
            // 只要有任何一种可以满足的可能，就可以放到结果集中
            if (MastermindMatchForE4b(element4b, guess) == matchResult) {
                newResultSet.add(element4b);
            }
        }
        return newResultSet;
    }

    /**
     * 缩减结果集
     *
     * @param resultSet   resultSet
     * @param guess       guess
     * @param matchResult matchResult
     * @return HashSet<Element4b>
     */
    public static HashSet<Element4b> concurrentGetNewResultSetE4b(HashSet<Element4b> resultSet, Element4b guess, int matchResult) {
        HashSet<Element4b> newResultSet = new HashSet<>();
        if (matchResult == MatchResultEnum.A4B0.value) {
            newResultSet.add(guess);
            return newResultSet;
        }
        for (Element4b element4b : resultSet) {
            // 只要有任何一种可以满足的可能，就可以放到结果集中
            if (concurrentMatchForE4b(element4b, guess) == matchResult) {
                newResultSet.add(element4b);
            }
        }
        return newResultSet;
    }

}
